<template>
  <div class="data-table-container">
    <div class="table-header">
      <h3>Redis 数据概览</h3>
      <div class="table-controls">
        <el-input
          v-model="searchPattern"
          placeholder="搜索键模式 (如: user:*, test:*)"
          class="search-input"
          @keyup.enter="refreshData"
        >
          <template #append>
            <el-button @click="refreshData" :loading="loading">
              <el-icon><Refresh /></el-icon>
            </el-button>
          </template>
        </el-input>
        <el-select v-model="pageSize" placeholder="每页显示" style="width: 120px;" @change="handlePageSizeChange">
          <el-option label="10条" :value="10" />
          <el-option label="20条" :value="20" />
          <el-option label="50条" :value="50" />
          <el-option label="100条" :value="100" />
        </el-select>
        <el-button type="primary" @click="refreshData" :loading="loading">
          刷新数据
        </el-button>
      </div>
    </div>

    <!-- 统计信息 -->
    <div class="stats-bar">
      <div class="stats-item">
        <span class="stats-label">总键数:</span>
        <span class="stats-value">{{ totalKeys }}</span>
      </div>
      <div class="stats-item">
        <span class="stats-label">当前显示:</span>
        <span class="stats-value">{{ tableData.length }}</span>
      </div>
      <div class="stats-item">
        <span class="stats-label">匹配模式:</span>
        <span class="stats-value">{{ searchPattern }}</span>
      </div>
      <div class="stats-item" v-if="loadTime">
        <span class="stats-label">加载耗时:</span>
        <span class="stats-value">{{ loadTime }}ms</span>
      </div>
    </div>

    <!-- 性能警告 -->
    <el-alert
      v-if="showPerformanceWarning"
      title="性能提示"
      type="warning"
      :closable="false"
      show-icon
      class="performance-warning"
    >
      <template #default>
        检测到大量键（{{ totalKeys }}个），为了性能考虑，建议使用更具体的搜索模式来过滤数据。
        当前限制显示前 {{ maxDisplayKeys }} 个键。
      </template>
    </el-alert>

    <el-table
      :data="paginatedData"
      v-loading="loading"
      stripe
      border
      height="400"
      class="data-table"
      :empty-text="emptyText"
    >
      <el-table-column prop="key" label="键" width="200" show-overflow-tooltip>
        <template #default="{ row }">
          <el-tag size="small" class="key-tag">{{ row.key }}</el-tag>
        </template>
      </el-table-column>

      <el-table-column prop="type" label="类型" width="100" align="center">
        <template #default="{ row }">
          <el-tag
            :type="getTypeTagType(row.type)"
            size="small"
          >
            {{ row.type.toUpperCase() }}
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column prop="value" label="值" min-width="300" show-overflow-tooltip>
        <template #default="{ row }">
          <div class="value-content">
            <span v-if="typeof row.value === 'string'" class="string-value">
              {{ truncateValue(row.value) }}
            </span>
            <div v-else-if="typeof row.value === 'object'" class="object-value">
              <pre>{{ truncateValue(JSON.stringify(row.value, null, 2)) }}</pre>
            </div>
            <span v-else class="other-value">{{ row.value }}</span>
          </div>
        </template>
      </el-table-column>

      <el-table-column prop="size" label="大小" width="100" align="center">
        <template #default="{ row }">
          <span class="size-text">{{ formatSize(row.size) }}</span>
        </template>
      </el-table-column>

      <el-table-column prop="ttl" label="TTL" width="120" align="center">
        <template #default="{ row }">
          <el-tag
            :type="getTTLTagType(row.ttl)"
            size="small"
          >
            {{ formatTTL(row.ttl) }}
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column label="操作" width="150" align="center">
        <template #default="{ row }">
          <el-button
            type="primary"
            size="small"
            @click="viewKey(row.key)"
            plain
          >
            查看
          </el-button>
          <el-button
            type="danger"
            size="small"
            @click="deleteKey(row.key)"
            :loading="deletingKeys.has(row.key)"
            plain
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="tableData.length"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handlePageSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

    <div class="table-footer">
      <span class="last-update">最后更新: {{ lastUpdateTime }}</span>
      <el-button size="small" @click="exportData" :disabled="tableData.length === 0">
        导出数据
      </el-button>
    </div>

    <!-- 查看键详情对话框 -->
    <el-dialog
      v-model="showKeyDialog"
      :title="`键详情: ${selectedKey}`"
      width="60%"
      :before-close="handleKeyDialogClose"
    >
      <div v-if="keyDetail" class="key-detail">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="键名">{{ keyDetail.key }}</el-descriptions-item>
          <el-descriptions-item label="类型">
            <el-tag :type="getTypeTagType(keyDetail.type)" size="small">
              {{ keyDetail.type.toUpperCase() }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="大小">{{ formatSize(keyDetail.size) }}</el-descriptions-item>
          <el-descriptions-item label="TTL">
            <el-tag :type="getTTLTagType(keyDetail.ttl)" size="small">
              {{ formatTTL(keyDetail.ttl) }}
            </el-tag>
          </el-descriptions-item>
        </el-descriptions>

        <div class="key-value-section">
          <h4>值内容:</h4>
          <div class="value-display">
            <pre v-if="typeof keyDetail.value === 'string'">{{ keyDetail.value }}</pre>
            <pre v-else>{{ JSON.stringify(keyDetail.value, null, 2) }}</pre>
          </div>
        </div>
      </div>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="copyKeyValue" :disabled="!keyDetail">复制值</el-button>
          <el-button type="primary" @click="showKeyDialog = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Refresh } from '@element-plus/icons-vue'
import { getAllKeys, del } from '../api/redis'

interface KeyInfo {
  key: string
  type: string
  value: any
  size: number
  ttl: number
}

const tableData = ref<KeyInfo[]>([])
const loading = ref(false)
const searchPattern = ref('*')
const lastUpdateTime = ref('')
const deletingKeys = ref(new Set<string>())
const totalKeys = ref(0)
const loadTime = ref(0)
const maxDisplayKeys = 1000 // 最大显示键数量

// 分页相关
const currentPage = ref(1)
const pageSize = ref(20)

// 键详情对话框
const showKeyDialog = ref(false)
const selectedKey = ref('')
const keyDetail = ref<KeyInfo | null>(null)

// 计算属性
const showPerformanceWarning = computed(() => totalKeys.value > 500)

const emptyText = computed(() => {
  if (loading.value) return '加载中...'
  if (searchPattern.value !== '*') return '没有匹配的键'
  return '暂无数据'
})

const paginatedData = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return tableData.value.slice(start, end)
})

// 刷新数据
const refreshData = async () => {
  loading.value = true
  const startTime = Date.now()

  try {
    const response = await getAllKeys(searchPattern.value)
    if (response.data.success) {
      let keys = response.data.keys || []
      totalKeys.value = keys.length

      // 性能优化：限制显示数量
      if (keys.length > maxDisplayKeys) {
        keys = keys.slice(0, maxDisplayKeys)
        ElMessage.warning(`数据量过大，仅显示前 ${maxDisplayKeys} 个键`)
      }

      tableData.value = keys
      lastUpdateTime.value = new Date().toLocaleString()
      loadTime.value = Date.now() - startTime

      // 重置分页
      currentPage.value = 1

      ElMessage.success(`成功获取 ${keys.length} 个键的信息`)
    } else {
      ElMessage.error(response.data.message || '获取数据失败')
    }
  } catch (error) {
    console.error('获取数据失败:', error)
    ElMessage.error('获取数据失败，请检查网络连接')
  } finally {
    loading.value = false
  }
}

// 查看键详情
const viewKey = (key: string) => {
  const keyInfo = tableData.value.find(item => item.key === key)
  if (keyInfo) {
    selectedKey.value = key
    keyDetail.value = keyInfo
    showKeyDialog.value = true
  }
}

// 复制键值
const copyKeyValue = () => {
  if (keyDetail.value) {
    const value = typeof keyDetail.value.value === 'string'
      ? keyDetail.value.value
      : JSON.stringify(keyDetail.value.value, null, 2)

    navigator.clipboard.writeText(value)
    ElMessage.success('已复制到剪贴板')
  }
}

// 关闭键详情对话框
const handleKeyDialogClose = (done: () => void) => {
  selectedKey.value = ''
  keyDetail.value = null
  done()
}

// 删除键
const deleteKey = async (key: string) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除键 "${key}" 吗？此操作不可恢复。`,
      '确认删除',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }
    )

    deletingKeys.value.add(key)
    const response = await del(key)

    if (response.data.success) {
      ElMessage.success('删除成功')
      // 从当前数据中移除，避免重新加载
      const index = tableData.value.findIndex(item => item.key === key)
      if (index > -1) {
        tableData.value.splice(index, 1)
        totalKeys.value--
      }
    } else {
      ElMessage.error(response.data.message || '删除失败')
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除失败:', error)
      ElMessage.error('删除失败')
    }
  } finally {
    deletingKeys.value.delete(key)
  }
}

// 导出数据
const exportData = () => {
  const csvContent = [
    ['键名', '类型', '值', '大小', 'TTL'].join(','),
    ...tableData.value.map(row => [
      row.key,
      row.type,
      typeof row.value === 'string' ? row.value.replace(/,/g, ';') : JSON.stringify(row.value).replace(/,/g, ';'),
      row.size,
      row.ttl
    ].join(','))
  ].join('\n')

  const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
  const link = document.createElement('a')
  const url = URL.createObjectURL(blob)
  link.setAttribute('href', url)
  link.setAttribute('download', `redis-keys-${Date.now()}.csv`)
  link.style.visibility = 'hidden'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)

  ElMessage.success('数据导出成功')
}

// 分页处理
const handlePageSizeChange = (val: number) => {
  pageSize.value = val
  currentPage.value = 1
}

const handleCurrentChange = (val: number) => {
  currentPage.value = val
}

// 截断长文本
const truncateValue = (value: string, maxLength: number = 100) => {
  if (value.length <= maxLength) return value
  return value.substring(0, maxLength) + '...'
}

// 工具函数
const getTypeTagType = (type: string) => {
  const typeMap: Record<string, string> = {
    string: 'success',
    hash: 'warning',
    list: 'info',
    set: 'primary',
    zset: 'danger'
  }
  return typeMap[type.toLowerCase()] || 'default'
}

const getTTLTagType = (ttl: number) => {
  if (ttl === -1) return 'info'  // 永不过期
  if (ttl === -2) return 'danger'  // 键不存在
  if (ttl < 60) return 'danger'  // 小于1分钟
  if (ttl < 3600) return 'warning'  // 小于1小时
  return 'success'  // 大于1小时
}

const formatTTL = (ttl: number) => {
  if (ttl === -1) return '永不过期'
  if (ttl === -2) return '键不存在'
  if (ttl < 60) return `${ttl}秒`
  if (ttl < 3600) return `${Math.floor(ttl / 60)}分钟`
  if (ttl < 86400) return `${Math.floor(ttl / 3600)}小时`
  return `${Math.floor(ttl / 86400)}天`
}

const formatSize = (size: number) => {
  if (size === 0) return '0 B'
  if (size < 1024) return `${size} B`
  if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`
  return `${(size / (1024 * 1024)).toFixed(1)} MB`
}

onMounted(() => {
  refreshData()
})
</script>

<style scoped>
.data-table-container {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  margin-top: 20px;
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.table-header h3 {
  margin: 0;
  color: #303133;
  font-size: 18px;
}

.table-controls {
  display: flex;
  gap: 10px;
  align-items: center;
}

.search-input {
  width: 300px;
}

.stats-bar {
  display: flex;
  gap: 20px;
  margin-bottom: 15px;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 6px;
  border-left: 4px solid #409EFF;
}

.stats-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.stats-label {
  font-size: 12px;
  color: #909399;
  margin-bottom: 2px;
}

.stats-value {
  font-size: 14px;
  font-weight: bold;
  color: #303133;
}

.performance-warning {
  margin-bottom: 15px;
}

.data-table {
  margin-bottom: 15px;
}

.key-tag {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-weight: bold;
}

.value-content {
  max-height: 80px;
  overflow-y: auto;
}

.string-value {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  color: #67C23A;
  font-size: 12px;
}

.object-value pre {
  margin: 0;
  font-size: 11px;
  color: #409EFF;
  white-space: pre-wrap;
  word-break: break-all;
}

.other-value {
  color: #909399;
  font-style: italic;
}

.size-text {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-weight: bold;
  color: #606266;
}

.pagination-container {
  display: flex;
  justify-content: center;
  margin: 20px 0;
}

.table-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
  border-top: 1px solid #EBEEF5;
  color: #909399;
  font-size: 14px;
}

.last-update {
  font-size: 12px;
}

/* 键详情对话框样式 */
.key-detail {
  max-height: 500px;
  overflow-y: auto;
}

.key-value-section {
  margin-top: 20px;
}

.key-value-section h4 {
  margin: 0 0 10px 0;
  color: #303133;
}

.value-display {
  background: #f8f9fa;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 15px;
  max-height: 300px;
  overflow-y: auto;
}

.value-display pre {
  margin: 0;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 13px;
  line-height: 1.5;
  color: #2c3e50;
  white-space: pre-wrap;
  word-break: break-all;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .stats-bar {
    flex-wrap: wrap;
    gap: 15px;
  }
}

@media (max-width: 768px) {
  .table-header {
    flex-direction: column;
    gap: 15px;
    align-items: stretch;
  }

  .table-controls {
    flex-direction: column;
    gap: 10px;
  }

  .search-input {
    width: 100%;
  }

  .stats-bar {
    flex-direction: column;
    gap: 10px;
  }

  .stats-item {
    flex-direction: row;
    justify-content: space-between;
  }

  .table-footer {
    flex-direction: column;
    gap: 10px;
    align-items: center;
  }

  .pagination-container {
    overflow-x: auto;
  }
}
</style>